package cn.boodqian.d3surveyor;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import cn.boodqian.util.Log;
import android.widget.SimpleCursorAdapter;

class DrawableImage {
	String filename;
	int drawable_id;
}

public class D3DB {
	public static enum Lang {
		EN, ZH_CN, ZH_TW
	};
	private static D3DB m_Instance = null;
	private SQLiteDatabase mDB;
	private Lang m_lang = Lang.EN; // 1 = english, 2 = Chinese, 3 = chinese taiwan
	private static Context m_context;
	private ArrayList<DrawableImage> m_drawables = new ArrayList<DrawableImage>();
	private ArrayList<HashMap<String, String>> m_Langs = null;
	
	public Cursor m_pTypeCursor = null;  // profession
	public Cursor m_epTypeCursor = null;  // equipment part type
	public Cursor m_eTypeCursor = null;  // equipment type
	public Cursor m_mTypeCursor = null;  // magic property type
	public Cursor m_lTypeCursor = null;  // magic level type
	
	private int m_currentPType = 0;
	private int m_currentEPType = 0;
	private int m_currentEType = 0;
	private D3SurveyorDBHelper mDBHelper;
	
	public Lang getLang() {
		return m_lang;
	}
	public void setProfessionType(int type) {
		m_currentPType = type;
	}
	public int getProfessionType() {
		return m_currentPType;
	}
	public void setEquipmentType(int type) {
		m_currentEType = type;
	}
	public int getEquipmentType() {
		return m_currentEType;
	}
	public void setPartType(int type) {
		m_currentEPType = type;
	}
	public int getPartType() {
		return m_currentEPType;
	}
	/*
	 * Profession masks
	 *     1 - Barbarian
	 *     2 - Monk
	 *     4 - Demon Hunter
	 *     8 - Wizard
	 *    16 - Witch Doctor
	 * */
	private int getProfessionFlag(int pType) {
		return 1<<(pType-1);
	}
	
	public int getDefaultPType() {
		// for some cases that need a profession ID, give barbarian
		return 1;
	}
	
	public int getDefaultPartType() {
		// return the head
		return 1000;
	}

	public static D3DB getInstance(Context context) {
		m_context = context;
		if(m_Instance==null) {
			Log.i("new instance of D3DB");
			m_Instance = new D3DB();
		}
		return m_Instance;
	}
	
	public static D3DB getNewInstance(Context context) {
		if(m_Instance!=null) {
			m_Instance.getDBHelper().getReadableDatabase().close();
			m_Instance = null;
		}
		return D3DB.getInstance(context);
	}
	
	public static Context getAppContext() {
		return m_context;
	}
	
	private D3DB() {
		// m_appContext = getApplicationContext();
		init();
		refreshDataByLanguage(Lang.EN);
	}
	
	private void init() {
		mDBHelper = new D3SurveyorDBHelper(m_context);
		
		mDB = mDBHelper.getReadableDatabase();
		loadDrawableIds();
	}
	
	private void loadDrawableIds() {
		/* add drawable ids into the array list*/
		Class<cn.boodqian.d3surveyor.R.drawable> c = R.drawable.class;
		for (Field f : c.getFields()) {
			try {
				DrawableImage di = new DrawableImage();
				di.filename = f.getName();
				di.drawable_id = f.getInt(f);
				m_drawables.add(di);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	public int getItemDrawableId() {
		String f_name = "i" + String.valueOf(m_currentPType) + "_" + String.valueOf(m_currentEType);
		for (DrawableImage di : m_drawables) {
			if (di.filename.equals(f_name)) {
				return di.drawable_id;
			}
		}
		return 0;
	}
	
	@SuppressWarnings({ "deprecation" })
	public SimpleCursorAdapter cursorToAdapter(Cursor cursor, int layout) {
		SimpleCursorAdapter adapter = null;
		if (m_lang == Lang.ZH_TW) {
			 adapter = new SimpleCursorAdapter(
					m_context,
					layout, 
					cursor,
					new String[]{"chinesetw"}, new int[]{android.R.id.text1});
		} else if (m_lang == Lang.ZH_CN) {
			 adapter = new SimpleCursorAdapter(
					m_context,
					layout, 
					cursor,
					new String[]{"chinese"}, new int[]{android.R.id.text1});
		} else {
			adapter = new SimpleCursorAdapter(
					m_context,
					layout, 
					cursor,
					new String[]{"english"}, new int[]{android.R.id.text1});
		}
		adapter.setDropDownViewResource(R.layout.spinner_dropdown);
		return adapter;
	}
	
	public int getCursorType(Cursor cursor) {
		return cursor.getInt(cursor.getColumnIndex("type"));
	}
	
	public String getCursorName(Cursor cursor) {
		if (m_lang == Lang.ZH_TW) {
			return cursor.getString(cursor.getColumnIndex("chinesetw"));
		} else if (m_lang == Lang.ZH_CN) {
			return cursor.getString(cursor.getColumnIndex("chinese"));
		} else {
			return cursor.getString(cursor.getColumnIndex("english"));
		}
	}
	
	public String getNameByType(Cursor cursor, int type) {
		cursor.moveToFirst();
		do {
			if (getCursorType(cursor)==type) {
				return getCursorName(cursor);
			}
		} while(cursor.moveToNext());
		return "Error";
	}
	
	public boolean isMagicPercentage(int type) {
		m_mTypeCursor.moveToFirst();
		do {
			if (getCursorType(m_mTypeCursor)==type) {
				int b = m_mTypeCursor.getInt(m_mTypeCursor.getColumnIndex("percentage"));
				return (b == 1)?true:false;
			}
		} while(m_mTypeCursor.moveToNext());
		return false;
	}
	
	public void refreshProfession() {
		if(m_pTypeCursor!=null) m_pTypeCursor.close();
		m_pTypeCursor = selectAllProfession();
	}
	
	public void refreshLevelType() {
		if(m_lTypeCursor!=null) m_lTypeCursor.close();
		m_lTypeCursor = selectAllLevelType();
	}
	
	public void refreshEquipType() {
		if(m_epTypeCursor!=null) m_epTypeCursor.close();
		m_epTypeCursor = selectEquipPartType();
		if(m_eTypeCursor!=null) m_eTypeCursor.close();
		m_eTypeCursor = selectSubEquipType();
	}
	
	public void refreshMagicType() {
		if(m_mTypeCursor!=null) m_mTypeCursor.close();
		m_mTypeCursor = selectAllMagicType();
	}
	
	public void refreshDataByLanguage(Lang l) {
		Log.i("lang="+l);
		m_lang = l;
		refreshProfession();
		refreshLevelType();
		refreshEquipType();
		refreshMagicType();
	}
	
	public Cursor selectAllProfession() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_profession");
		return query.query(mDB, new String[] {"rowid as _id", "*"}, "type<>0", null, null, null, null); // No "All profession"
	}
	
	public Cursor selectAllLevelType() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_level_type");
		return query.query(mDB, new String[] {"rowid as _id", "*"}, null, null, null, null, null);
	}
	
	public Cursor selectEquipPartType() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_equipment_type");
		return query.query(mDB, 
				new String[] {"rowid as _id", "*"}, 
				"d3_equipment_type.type%100=0 AND d3_equipment_type.type>=400", null , null, null, null);
	}
		
	public Cursor selectSubEquipType() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_equipment_type");
		int flag = getProfessionFlag(m_currentPType);
		return query.query(mDB, 
				new String[] {"rowid as _id", "*"},
				"d3_equipment_type.type%100<>0 AND d3_equipment_type.type/100="+m_currentEPType+"/100 " +
				"AND d3_equipment_type.p_types&"+flag+"="+flag, 
				null, null, null, null);
	}
	
	public Cursor selectAllSubEquipType() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_equipment_type");
		return query.query(mDB, 
				new String[] {"rowid as _id", "*"},
				"d3_equipment_type.type%100<>0", 
				null, null, null, null);
	}
	
	public Cursor selectAllMagicType() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_magic_property");
		return query.query(mDB, new String[] {"rowid as _id", "*"}, null, null, null, null, null);
	}
	
	public Cursor selectPropertyLevel(ArrayList<Long> selectedList) {
		// not complete, just copied 
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_property_level, d3_equipment_value");
		Log.i("selected: "+selectedList.toString());
		for(int i=0;i<selectedList.size();i++) {
			if(i>0) query.appendWhere(" AND ");
			query.appendWhere("d3_property_level.rowid<>"+selectedList.get(i));
		}
		
		Cursor cursor = query.query(mDB,
			new String[] {
				"d3_property_level.rowid as _id",
				"d3_property_level.m_type as m_type",
				"d3_property_level.level as l_type",
				"d3_equipment_value.minvalue as minvalue",
				"d3_equipment_value.maxvalue as maxvalue",
			},
			"d3_property_level.e_type="+m_currentEType+
			" AND d3_property_level.p_type="+m_currentPType+
			" AND (d3_property_level.m_type<5 OR d3_property_level.m_type>9)"+
			" AND d3_property_level.m_type=d3_equipment_value.m_type"+
			" AND d3_property_level.e_type=d3_equipment_value.e_type",
			null, null, null,
			"d3_property_level.level");
		
		return cursor;
	}
	
	public Cursor selectSelectedPropertyLevel(ArrayList<Long> selectedList) {
		// not complete, just copied 
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_property_level, d3_equipment_value");
		Log.i("selected: "+selectedList.toString());
		query.appendWhere("0=1 ");
		for(int i=0;i<selectedList.size();i++) {
			query.appendWhere(" OR d3_property_level.rowid="+selectedList.get(i));
		}
		Cursor cursor = query.query(mDB,
			new String[] {
				"d3_property_level.rowid as _id",
				"d3_property_level.m_type as m_type",
				"d3_property_level.level as l_type",
				"d3_equipment_value.minvalue as minvalue",
				"d3_equipment_value.maxvalue as maxvalue",
			},
			"d3_property_level.e_type="+m_currentEType+
			" AND d3_property_level.p_type="+m_currentPType+
			" AND (d3_property_level.m_type<5 OR d3_property_level.m_type>9)"+
			" AND d3_property_level.m_type=d3_equipment_value.m_type"+
			" AND d3_property_level.e_type=d3_equipment_value.e_type",
			null, null, null,
			"d3_property_level.level");
		return cursor;
	}
	
	public Cursor selectBaseProperty() {
		SQLiteQueryBuilder query = new SQLiteQueryBuilder();
		query.setTables("d3_equipment_value");
		Cursor cursor = query.query(mDB,
				new String[] {
					"d3_equipment_value.m_type as m_type",
					"d3_equipment_value.minvalue as minvalue",
					"d3_equipment_value.maxvalue as maxvalue",
				},
				"d3_equipment_value.e_type="+m_currentEType+
				" AND (d3_equipment_value.m_type==5"+
					" OR d3_equipment_value.m_type==8"+
					" OR d3_equipment_value.m_type==9"+
				")",
				null, null, null, null);
		return cursor;
	}
	
	public List selectLang() {
		if(m_Langs ==null ) {
			HashMap<String, String> map;
			m_Langs = new ArrayList<HashMap<String,String>>();
			map = new HashMap<String, String>();
			map.put("name", m_context.getString(R.string.lang_en));
			map.put("lang", Lang.EN.toString());
			m_Langs.add(map);
			map = new HashMap<String, String>();
			map.put("name", m_context.getString(R.string.lang_zh_cn));
			map.put("lang", Lang.ZH_CN.toString());
			m_Langs.add(map);
			map = new HashMap<String, String>();
			map.put("name", m_context.getString(R.string.lang_zh_tw));
			map.put("lang", Lang.ZH_TW.toString());
			m_Langs.add(map);
		}
		return m_Langs;
	}
	
	public D3SurveyorDBHelper getDBHelper() {
		return (D3SurveyorDBHelper)mDBHelper;
	}
}